package mil.nga.giat.mage.sdk.http.resource; import android.content.Context; import android.preference.PreferenceManager; import android.util.Log; import com.google.gson.JsonObject; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.ResponseBody; import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import mil.nga.giat.mage.sdk.R; import mil.nga.giat.mage.sdk.datastore.DaoStore; import mil.nga.giat.mage.sdk.datastore.observation.Attachment; import mil.nga.giat.mage.sdk.datastore.observation.Observation; import mil.nga.giat.mage.sdk.datastore.observation.ObservationFavorite; import mil.nga.giat.mage.sdk.datastore.observation.ObservationHelper; import mil.nga.giat.mage.sdk.datastore.observation.ObservationImportant; import mil.nga.giat.mage.sdk.datastore.user.Event; import mil.nga.giat.mage.sdk.http.HttpClientManager; import mil.nga.giat.mage.sdk.http.converter.AttachmentConverterFactory; import mil.nga.giat.mage.sdk.http.converter.ObservationConverterFactory; import mil.nga.giat.mage.sdk.http.converter.ObservationImportantConverterFactory; import mil.nga.giat.mage.sdk.http.converter.ObservationsConverterFactory; import mil.nga.giat.mage.sdk.utils.ISO8601DateFormatFactory; import mil.nga.giat.mage.sdk.utils.MediaUtility; import retrofit.Call; import retrofit.Response; import retrofit.Retrofit; import retrofit.http.Body; import retrofit.http.DELETE; import retrofit.http.GET; import retrofit.http.Multipart; import retrofit.http.POST; import retrofit.http.PUT; import retrofit.http.PartMap; import retrofit.http.Path; import retrofit.http.Query; import retrofit.http.Streaming; /*** * RESTful communication for observations * * @author newmanw */ public class ObservationResource { public interface ObservationService { @GET("/api/events/{eventId}/observations") Call<Collection<Observation>> getObservations(@Path("eventId") String eventId, @Query("startDate") String startDate); @POST("/api/events/{eventId}/observations") Call<Observation> createObservation(@Path("eventId") String eventId , @Body Observation observation); @PUT("/api/events/{eventId}/observations/{observationId}") Call<Observation> updateObservation(@Path("eventId") String eventId, @Path("observationId") String observationId, @Body Observation observation); @GET("/api/events/{eventId}/form/icons.zip") Call<ResponseBody> getObservationIcons(@Path("eventId") String eventId); @Streaming @GET("/api/events/{eventId}/observations/{observationId}/attachments/{attachmentId}") Call<ResponseBody> getAttachment(@Path("eventId") String eventId, @Path("observationId") String observationId, @Path("attachmentId") String attachmentId); @Multipart @POST("/api/events/{eventId}/observations/{observationId}/attachments") Call<Attachment> createAttachment(@Path("eventId") String eventId, @Path("observationId") String observationId, @PartMap Map<String, RequestBody> parts); @PUT("/api/events/{eventId}/observations/{observationId}/favorite") Call<Observation> favoriteObservation(@Path("eventId") String eventId, @Path("observationId") String observationId); @DELETE("/api/events/{eventId}/observations/{observationId}/favorite") Call<Observation> unfavoriteObservation(@Path("eventId") String eventId, @Path("observationId") String observationId); @PUT("/api/events/{eventId}/observations/{observationId}/important") Call<Observation> addImportant(@Path("eventId") String eventId, @Path("observationId") String observationId, @Body JsonObject important); @DELETE("/api/events/{eventId}/observations/{observationId}/important") Call<Observation> removeImportant(@Path("eventId") String eventId, @Path("observationId") String observationId); } private static final String LOG_NAME = ObservationResource.class.getName(); private Context context; public ObservationResource(Context context) { this.context = context; } public Collection<Observation> getObservations(Event event) { Collection<Observation> observations = new ArrayList<>(); if (event == null || event.getRemoteId() == null) { return observations; } String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ObservationsConverterFactory.create(event)) .client(HttpClientManager.getInstance(context).httpClient()) .build(); DateFormat iso8601Format = ISO8601DateFormatFactory.ISO8601(); ObservationHelper observationHelper = ObservationHelper.getInstance(context); Date lastModifiedDate = observationHelper.getLatestCleanLastModified(context, event); Log.d(LOG_NAME, "Fetching all observations after: " + iso8601Format.format(lastModifiedDate)); ObservationService service = retrofit.create(ObservationService.class); try { Response<Collection<Observation>> response = service.getObservations(event.getRemoteId(), iso8601Format.format(lastModifiedDate)).execute(); if (response.isSuccess()) { observations = response.body(); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } } catch (IOException e) { Log.e(LOG_NAME, "There was a failure while performing an Observation Fetch operation.", e); } return observations; } public Observation saveObservation(Observation observation) { ObservationHelper observationHelper = ObservationHelper.getInstance(context); Observation savedObservation = null; try { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ObservationConverterFactory.create(observation.getEvent())) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); Response<Observation> response; if (StringUtils.isEmpty(observation.getRemoteId())) { response = service.createObservation(observation.getEvent().getRemoteId(), observation).execute(); } else { response = service.updateObservation(observation.getEvent().getRemoteId(), observation.getRemoteId(), observation).execute(); } if (response.isSuccess()) { Observation returnedObservation = response.body(); returnedObservation.setDirty(Boolean.FALSE); returnedObservation.setId(observation.getId()); savedObservation = observationHelper.update(returnedObservation); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } } catch (Exception e) { Log.e(LOG_NAME, "Failure saving observation.", e); } return savedObservation; } public InputStream getObservationIcons(Event event) throws IOException { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); Response<ResponseBody> response = service.getObservationIcons(event.getRemoteId()).execute(); InputStream inputStream = null; if (response.isSuccess()) { inputStream = response.body().byteStream(); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } return inputStream; } public ResponseBody getAttachment(Attachment attachment) throws IOException { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); String eventId = attachment.getObservation().getEvent().getRemoteId(); String observationId = attachment.getObservation().getRemoteId(); String attachmentId = attachment.getRemoteId(); Response<ResponseBody> response = service.getAttachment(eventId, observationId, attachmentId).execute(); if (response.isSuccess()) { return response.body(); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } return null; } public Attachment createAttachment(Attachment attachment) { try { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(AttachmentConverterFactory.create()) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); String eventId = attachment.getObservation().getEvent().getRemoteId(); String observationId = attachment.getObservation().getRemoteId(); Map<String, RequestBody> parts = new HashMap<>(); File attachmentFile = new File(attachment.getLocalPath()); String mimeType = MediaUtility.getMimeType(attachment.getLocalPath()); RequestBody fileBody = RequestBody.create(MediaType.parse(mimeType), attachmentFile); parts.put("attachment\"; filename=\"" + attachmentFile.getName() + "\"", fileBody); Response<Attachment> response = service.createAttachment(eventId, observationId, parts).execute(); if (response.isSuccess()) { Attachment returnedAttachment = response.body(); attachment.setContentType(returnedAttachment.getContentType()); attachment.setName(returnedAttachment.getName()); attachment.setRemoteId(returnedAttachment.getRemoteId()); attachment.setRemotePath(returnedAttachment.getRemotePath()); attachment.setSize(returnedAttachment.getSize()); attachment.setUrl(returnedAttachment.getUrl()); attachment.setDirty(returnedAttachment.isDirty()); DaoStore.getInstance(context).getAttachmentDao().update(attachment); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } } catch (Exception e) { Log.e(LOG_NAME, "Failure saving observation.", e); } return attachment; } public Observation toogleFavorite(ObservationFavorite favorite) { ObservationHelper observationHelper = ObservationHelper.getInstance(context); Observation observation = favorite.getObservation(); Observation savedObservation = null; try { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ObservationConverterFactory.create(observation.getEvent())) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); Response<Observation> response; if (favorite.isFavorite()) { response = service.favoriteObservation(observation.getEvent().getRemoteId(), observation.getRemoteId()).execute(); } else { response = service.unfavoriteObservation(observation.getEvent().getRemoteId(), observation.getRemoteId()).execute(); } if (response.isSuccess()) { Observation returnedObservation = response.body(); ObservationFavorite returnedFavorite = returnedObservation.getFavoritesMap().get(favorite.getUserId()); if (returnedFavorite != null) { returnedFavorite.setDirty(Boolean.FALSE); } returnedObservation.setId(observation.getId()); savedObservation = observationHelper.update(returnedObservation); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } } catch (Exception e) { Log.e(LOG_NAME, "Failure toogling observation favorite.", e); } return savedObservation; } public Observation toogleImporant(Observation observation) { ObservationHelper observationHelper = ObservationHelper.getInstance(context); ObservationImportant important = observation.getImportant(); Observation savedObservation = null; try { String baseUrl = PreferenceManager.getDefaultSharedPreferences(context).getString(context.getString(R.string.serverURLKey), context.getString(R.string.serverURLDefaultValue)); Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ObservationImportantConverterFactory.create(observation.getEvent())) .client(HttpClientManager.getInstance(context).httpClient()) .build(); ObservationService service = retrofit.create(ObservationService.class); Response<Observation> response; if (important.isImportant()) { JsonObject jsonImportant = new JsonObject(); jsonImportant.addProperty("description", important.getDescription()); response = service.addImportant(observation.getEvent().getRemoteId(), observation.getRemoteId(), jsonImportant).execute(); } else { response = service.removeImportant(observation.getEvent().getRemoteId(), observation.getRemoteId()).execute(); } if (response.isSuccess()) { Observation returnedObservation = response.body(); important.setDirty(Boolean.FALSE); returnedObservation.setId(observation.getId()); savedObservation = observationHelper.update(returnedObservation); } else { Log.e(LOG_NAME, "Bad request."); if (response.errorBody() != null) { Log.e(LOG_NAME, response.errorBody().string()); } } } catch (Exception e) { Log.e(LOG_NAME, "Failure toogling observation important.", e); } return savedObservation; } }